﻿using System;
using System.Collections.Generic;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WikeSoft.WorkFlowEngine.Entities;
using WikeSoft.WorkFlowEngine.Enum;
using WikeSoft.WorkFlowEngine.Extension;
using WikeSoft.WorkFlowEngine.Filter;
using WikeSoft.WorkFlowEngine.Interfaces;
using WikeSoft.WorkFlowEngine.Models;

namespace WikeSoft.WorkFlowEngine.AppServices
{
    public  class WorkFlowCategoryService: IWorkFlowCategoryService
    {

        private string GetPathCode(string parentPageId)
        {
            using (var context = new WorkFlowDbContext())
            {
                //顶级页面
                List<string> existCodes = new List<string>();
                var parentPathCode = string.Empty;
                if (string.IsNullOrEmpty(parentPageId))
                {
                    existCodes = context.WorkFlowCategories.Where(x => x.ParentId == null || x.ParentId == string.Empty)
                         .Select(x => x.PathCode).ToList();
                }
                else
                {
                    var page = context.WorkFlowCategories.Find(parentPageId);
                    if (page != null)
                    {
                        parentPathCode = page.PathCode;
                        existCodes = context.WorkFlowCategories.Where(x => x.ParentId == parentPageId).Select(x => x.PathCode).ToList().Select(x => x.Substring(page.PathCode.Length, 2)).ToList();
                    }
                }
                var pathCode = this.SysPathCodes.First(x => !existCodes.Contains(x));
                return parentPathCode + pathCode;
            }
            
        }

        public List<string> SysPathCodes
        {
            get
            {
                return new List<string>()
                {
                    "AA","AB","AC","AD","AE","AF","AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ",
                    "BA","BB","BC","BD","BE","BF","BG", "BH", "BI", "BJ", "BK", "BL", "BM", "BN", "BO", "BP", "BQ", "BR", "BS", "BT", "BU", "BV", "BW", "BX", "BY", "BZ",
                    "CA","CB","CC","CD","CE","CF","CG", "CH", "CI", "CJ", "CK", "CL", "CM", "CN", "CO", "CP", "CQ", "CR", "CS", "CT", "CU", "CV", "CW", "CX", "CY", "CZ",
                    "DA","DB","DC","DD","DE","DF","DG", "DH", "DI", "DJ", "DK", "DL", "DM", "DN", "DO", "DP", "DQ", "DR", "DS", "DT", "DU", "DV", "DW", "DX", "DY", "DZ",
                };
            }
        } 
        public FlowMessage Add(WorkFlowCategoryModel model)
        {
            FlowMessage flowMessage = new FlowMessage();
            try
            {
                using (var context = new WorkFlowDbContext())
                {
                    WorkFlowCategory workFlowCategory = new WorkFlowCategory();
                    workFlowCategory.Id = Guid.NewGuid().ToString().ToUpper();
                    workFlowCategory.CategoryName = model.CategoryName;
                    workFlowCategory.SortIndx = model.SortIndx; 
                    workFlowCategory.ParentId = model.ParentId;
                    workFlowCategory.PathCode = GetPathCode(model.ParentId);
                    context.WorkFlowCategories.Add(workFlowCategory);
                    context.SaveChanges();
                    

                }
            }
            catch (Exception ex)
            {
                flowMessage.Code = CodeEum.Fail;
                flowMessage.Message = ex.Message;
            }
            return flowMessage;
        }

        public FlowMessage Edit(WorkFlowCategoryModel model)
        {
            FlowMessage flowMessage = new FlowMessage();
            try
            {
                using (var context = new WorkFlowDbContext())
                {
                    WorkFlowCategory workFlowCategory = context.WorkFlowCategories.FirstOrDefault(x => x.Id == model.Id);
                    if (workFlowCategory != null)
                    {
                        workFlowCategory.CategoryName = model.CategoryName;
                        workFlowCategory.SortIndx = model.SortIndx;
                        workFlowCategory.ParentId = model.ParentId;

                        var subs = context.WorkFlowCategories.Where(c => c.PathCode.StartsWith(workFlowCategory.PathCode) && c.Id != model.Id).ToList();
                        var subIds = subs.Select(c => c.Id).ToList();
                        if (subIds.Contains(model.ParentId))
                        {
                            throw new Exception("上级节点不能为当前节点的下级节点");
                        }
                        if (model.Id == model.ParentId)
                        {
                            throw new Exception("上级节点不能为当前节点");
                        }
                        var oldId = workFlowCategory.ParentId;
                        var newId = model.ParentId;
                        var oldPathCode = workFlowCategory.PathCode;
                       


                        if (oldId!=null && !oldId.Equals(newId))
                        {
                            var pathCode = GetPathCode(newId);

                            subs.ForEach(c =>
                            {
                                c.PathCode = c.PathCode.Replace(oldPathCode, pathCode);
                            });

                            workFlowCategory.PathCode = pathCode;
                        }

                        context.WorkFlowCategories.AddOrUpdate(workFlowCategory);

                    }
                    else
                    {
                        throw new Exception($"找不到WorkFlowCategory对象:{model.Id}");
                    }
                    context.SaveChanges();


                }
            }
            catch (Exception ex)
            {
                flowMessage.Code = CodeEum.Fail;
                flowMessage.Message = ex.Message;
            }
            return flowMessage;
        }

        public FlowMessage Delete(string id)
        {

            FlowMessage flowMessage = new FlowMessage();
            try
            {
                using (var context = new WorkFlowDbContext())
                {
                    WorkFlowCategory workFlowCategory = context.WorkFlowCategories.FirstOrDefault(x => x.Id == id);
                    if (workFlowCategory != null)
                    {
                        if (workFlowCategory.WorkFlowDefs.Count > 0)
                        {
                            throw new Exception("已关联流程定义，不能删除");
                        }
                        var count = context.WorkFlowCategories.Count(c => c.ParentId == id );
                        if (count > 0)
                        {
                            throw new Exception("请先删除下级数据");
                        }
                        context.WorkFlowCategories.Remove(workFlowCategory);

                    }
                    else
                    {
                        throw new Exception($"找不到WorkFlowCategory对象:{id}");
                    }

                    context.SaveChanges();


                }
            }
            catch (Exception ex)
            {
                flowMessage.Code = CodeEum.Fail;
                flowMessage.Message = ex.Message;
            }
            return flowMessage;
        }

        public IList<ZTreeEntity> GetByParentId(string parentId)
        {
            using (var context = new WorkFlowDbContext())
            {

                var query = context.WorkFlowCategories.AsQueryable();

                if (string.IsNullOrEmpty(parentId))
                {
                    query = query.Where(x => x.ParentId == null ||  x.ParentId == string.Empty);
                }
                else
                {
                    query = query.Where(x => x.ParentId == parentId);
                }
                 
                return query.OrderBy(x => x.SortIndx).Select(x => new ZTreeEntity
                {
                    id = x.Id,
                    name = x.CategoryName,
                    isParent = context.WorkFlowCategories.Any(p => p.ParentId == x.Id)
                }).ToList();
            }
        }

        public WorkFlowCategoryModel Find(string id)
        {
            WorkFlowCategoryModel model = new WorkFlowCategoryModel();

            using (var context = new WorkFlowDbContext())
            {
                var data = context.WorkFlowCategories.Find(id);

                if (data != null)
                {
                    model.Id = data.Id;
                    model.CategoryName = data.CategoryName;
                    model.SortIndx = data.SortIndx;
                    model.ParentId = data.ParentId;
                    if (!string.IsNullOrEmpty(data.ParentId))
                    {
                        var father = context.WorkFlowCategories.Find(data.ParentId);
                        if (father != null)
                        {
                            model.ParentName = father.CategoryName;
                        }
                    }
                }

            }
            return model;
        }

        public PagedResult<WorkFlowCategoryModel> Query(WorkFlowCategoryFilter filter)
        {
            using (var context = new WorkFlowDbContext())
            {

                var query = context.WorkFlowCategories.AsQueryable();
                if (!string.IsNullOrEmpty(filter.keywords))
                {
                    query = query.Where(c => c.CategoryName.Contains(filter.keywords));
                }
                return query.OrderByCustom(filter.sidx, filter.sord)
                    .Select(item => new WorkFlowCategoryModel
                    {
                        Id = item.Id,
                        CategoryName = item.CategoryName,
                         SortIndx = item.SortIndx,
                        ParentId = item.ParentId,
                     }).Paging(filter.page, filter.rows);
            }
        }
    }
}
